package org.locate.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;

import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SiteController {

	private static final long serialVersionUID = 1L;

	private FoursquareMgr oAuth;

	/**
	 * @param oAuth
	 *            the oAuth to set
	 */
	public void setoAuth(FoursquareMgr oAuth) {
		this.oAuth = oAuth;
	}

	@InitBinder
	public void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		binder.registerCustomEditor(String.class,
				new StringTrimmerEditor(false));
	}

	@RequestMapping("/finder.do")
	public ModelAndView finder() throws IllegalArgumentException, IOException,
			OAuthMessageSignerException, OAuthExpectationFailedException,
			OAuthCommunicationException, OAuthNotAuthorizedException {

		ModelAndView modelAndView = new ModelAndView("finder");
		modelAndView.addObject("foursquareForm", new FoursquareForm());
		return modelAndView;

	}

	@RequestMapping("/doOAuth.do")
	public ModelAndView doOAuth(
			@RequestParam("userSearches") String userSearches,
			HttpServletRequest servletRequest) throws IllegalArgumentException,
			IOException, OAuthMessageSignerException,
			OAuthExpectationFailedException, OAuthCommunicationException,
			OAuthNotAuthorizedException {

		servletRequest.getSession().setAttribute("userSearhes", userSearches);
		String authUrl = "";

		try {
			authUrl = oAuth.connect();

		} catch (Exception exp) {
			ModelAndView modelAndView = new ModelAndView("finder");
			modelAndView.addObject("foursquareForm", new FoursquareForm());
			modelAndView.addObject("foursquareErr", "foursquareErr");
			return modelAndView;
		}

		ModelAndView modelAndView = new ModelAndView("redirect:" + authUrl);
		return modelAndView;

	}

	@RequestMapping("/authCallBack.do")
	public ModelAndView authCallBack(
			@RequestParam("oauth_token") String pinCode,
			HttpServletRequest servletRequest) {

		AccessToken accessToken = null;

		try {

			accessToken = oAuth.requestAccessToken(pinCode);

		} catch (Exception exp) {
			ModelAndView modelAndView = new ModelAndView("finder");
			modelAndView.addObject("foursquareForm", new FoursquareForm());
			modelAndView.addObject("foursquareErr", "foursquareErr");
			return modelAndView;
		}

		String searchKeywords = (String) servletRequest.getSession()
				.getAttribute("userSearhes");
		servletRequest.getSession().removeAttribute("userSearhes");

		FoursquareForm form = new FoursquareForm();
		form.setPinCode(accessToken.getPinCode());
		form.setSecretToken(accessToken.getTokenSecret());
		form.setToken(accessToken.getToken());

		ModelAndView modelAndView = new ModelAndView("finder");
		modelAndView.addObject("foursquareForm", form);
		modelAndView.addObject("userSearches", setUserSearches(searchKeywords));
		modelAndView.addObject("loggedIn", "loggedIn");
		return modelAndView;

	}

	@RequestMapping("/checkin.do")
	public ModelAndView checkin(
			@ModelAttribute("foursquareForm") FoursquareForm foursquareForm)
			throws IllegalArgumentException, IOException,
			OAuthCommunicationException, OAuthMessageSignerException, OAuthExpectationFailedException {

		AccessToken accessToken = new AccessToken();
		accessToken.setPinCode(foursquareForm.getPinCode());
		accessToken.setToken(foursquareForm.getToken());
		accessToken.setTokenSecret(foursquareForm.getSecretToken());

		String checkin = "";

		try {
			checkin = oAuth.checkin(accessToken, foursquareForm);					
		} catch (OAuthMessageSignerException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";			
			throw e;
		} catch (OAuthExpectationFailedException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";
			throw e;
		} catch (OAuthCommunicationException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";
			throw e;
		} finally {

			ModelAndView modelAndView = new ModelAndView("checkin");
			modelAndView.addObject("foursquareForm", foursquareForm);
			modelAndView.addObject("checkin", checkin);
			return modelAndView;
		}

	}

	@RequestMapping("/tips.do")
	public ModelAndView tips(
			@ModelAttribute("foursquareForm") FoursquareForm foursquareForm)
			throws IllegalArgumentException, IOException,
			OAuthCommunicationException, OAuthMessageSignerException, OAuthExpectationFailedException {

		AccessToken accessToken = new AccessToken();
		accessToken.setPinCode(foursquareForm.getPinCode());
		accessToken.setToken(foursquareForm.getToken());
		accessToken.setTokenSecret(foursquareForm.getSecretToken());

		String checkin = "";

		try {
			checkin = oAuth.tips(accessToken, foursquareForm);					
		} catch (OAuthMessageSignerException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";			
			throw e;
		} catch (OAuthExpectationFailedException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";
			throw e;
		} catch (OAuthCommunicationException e) {
			checkin = "Foursquare is unable to process your check in. Please try again later.";
			throw e;
		} finally {

			ModelAndView modelAndView = new ModelAndView("checkin");
			modelAndView.addObject("foursquareForm", foursquareForm);
			modelAndView.addObject("checkin", checkin);
			return modelAndView;
		}

	}
	
	private List<String> setUserSearches(String searchWords) {
		List<String> userSearches = new ArrayList<String>();
		StringTokenizer stringTokenizer = new StringTokenizer(searchWords, ",");
		while (stringTokenizer.hasMoreElements()) {
			userSearches.add(stringTokenizer.nextToken());
		}

		return userSearches;
	}

}
